package com.wy2.eclipse.tool.logger;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.preferences.ScopedPreferenceStore;
import org.osgi.framework.BundleContext;
import org.slf4j.ILoggerFactory;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.SubstituteLoggerFactory;

import com.wy2.eclipse.tool.lib.common.IDEUtils;
import com.wy2.eclipse.tool.lib.git.GitJob;
import com.wy2.eclipse.tool.lib.neoodb.SessionManager;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.StatusPrinter;

/**
 * The activator class controls the plug-in life cycle
 */
public class LogActivator extends AbstractUIPlugin {
    
    private final static org.slf4j.Logger logger=LoggerFactory.getLogger(LogActivator.class);

	// The plug-in ID
	public static final String PLUGIN_ID = "com.wy2.eclipse.tool.logger"; //$NON-NLS-1$

	// The shared instance
	private static LogActivator plugin;
	
	
	/**
	 * 控制台名称
	 */
	public static final String CONSOLE_NAME="ToolSuiteConsole";
	public static final String PLUGIN_LOG_DIR="com.wy2.eclipse.tool.ui.log.dir";
	public static final String PLUGIN_LOG_NAME="com.wy2.eclipse.tool.ui.pluginName";
	
	private BundleContext bundleContext;
    private boolean isConfigured;
    private Timer timer = new Timer("logback configurator timer");

	  private TimerTask timerTask = new TimerTask() {
	    @SuppressWarnings("synthetic-access")
	    public void run() {
	      if(!isStateLocationInitialized()) {
	        return;
	      }

	      // The state location was initialized
	      timer.cancel();
	      Display.getDefault().syncExec(new Runnable() {
            
            @Override
            public void run() {
                configureLogback();
            }
          });
	      
	    }
	  };
	  
	  private boolean isStateLocationInitialized() {
		    if(!Platform.isRunning()) {
		      return false;
		    }
		    return true;
	 }
	
	/**
	 * The constructor
	 */
	public LogActivator() {
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
	 */
	public void start(BundleContext context) throws Exception {
		super.start(context);
		plugin = this;
		
		//getDefaultConsole().info("插件开始初始化...");

		bundleContext = context;
		LoggerInitJob loggerInitJob=new LoggerInitJob("初始化日志", bundleContext);
		loggerInitJob.addJobChangeListener(new JobChangeAdapter() {
            @Override
            public void done(IJobChangeEvent event) {
              final IStatus result = event.getResult();
              final LoggerInitJob job=(LoggerInitJob) event.getJob();
              if(result.isOK()) {
                  logger.info("{} 成功", job.getName());
                  
              }else {
                  
              }
              
            }
        });
		loggerInitJob.schedule();
		
//		if (!isStateLocationInitialized()) {
//			systemOut("The " + PLUGIN_ID //$NON-NLS-1$
//					+ " bundle was activated before the state location was initialized.  Will retry after the state location is initialized."); //$NON-NLS-1$
//			timer.schedule(timerTask, 0 /* delay */, 50 /* period */);
//		} else {
//			configureLogback();
//		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext context) throws Exception {
		plugin = null;
		//getDefaultConsole().info("com.wy2.eclipse.tool.logger:插件结束...");
		super.stop(context);
	}

	
	



	private ScopedPreferenceStore preferenceStore;
	
	  @Override
	  public IPreferenceStore getPreferenceStore() {
	    // Create the preference store lazily.
	    if(preferenceStore == null) {
	      // InstanceScope.INSTANCE added in 3.7
	      preferenceStore = new ScopedPreferenceStore(new InstanceScope(), PLUGIN_ID);

	    }
	    return preferenceStore;
	  }
	
	public ToolSuiteConsole getDefaultConsole() {
		return ToolSuiteConsole.getInstance(true);
	}
	
	/**
	 * 配置目录
	 * @return
	 */
	public String getConfigPath() {
		//String path= IDEUtils.getInstallLocation().toOSString()+"jdpdata";
		File file=new File(IDEUtils.getInstallLocation().toOSString(), "toolsuitedata");
		if(!file.exists()) {
			file.mkdir();
		}
		return file.getAbsolutePath();
	}
	
	private synchronized void configureLogback() {
	    if(isConfigured) {
	      systemOut("Logback was configured already"); //$NON-NLS-1$
	      return;
	    }

	    try {
	      //File stateDir = getStateLocation().toFile();
	      File stateDir=new File(getConfigPath(), "log");

	      File configFile = new File(stateDir, "logback." + bundleContext.getBundle().getVersion().toString() + ".xml"); //$NON-NLS-1$  //$NON-NLS-2$
	      systemOut("Logback config file: " + configFile.getAbsolutePath()); //$NON-NLS-1$
	      getDefaultConsole().info("Logback config file: " + configFile.getAbsolutePath());

	      if(!configFile.isFile()) {
	        // Copy the default config file to the actual config file
	        InputStream is = bundleContext.getBundle().getEntry("logbackconfiguration/logback.xml").openStream(); //$NON-NLS-1$
	        try {
	          configFile.getParentFile().mkdirs();
	          FileOutputStream fos = new FileOutputStream(configFile);
	          try {
	            for(byte[] buffer = new byte[1024 * 4];;) {
	              int n = is.read(buffer);
	              if(n < 0) {
	                break;
	              }
	              fos.write(buffer, 0, n);
	            }
	          } finally {
	            fos.close();
	          }
	        } finally {
	          is.close();
	        }
	      }

	      if(System.getProperty(PLUGIN_LOG_DIR, "").length() <= 0) { //$NON-NLS-1$
	        System.setProperty(PLUGIN_LOG_DIR, stateDir.getAbsolutePath());
	      }
	      if(System.getProperty(PLUGIN_LOG_NAME, "").length() <= 0) { //$NON-NLS-1$
		        System.setProperty(PLUGIN_LOG_NAME, "wy2ToolSuite");
		      }
	      //loadConfiguration(configFile.toURL());

	      isConfigured = true;
	    } catch(Exception e) {
	      e.printStackTrace();
	      getLog().log(new Status(IStatus.WARNING, PLUGIN_ID, "Exception while setting up logging:" + e.getMessage(), e)); //$NON-NLS-1$
	      return;
	    }
	  }

	  public void loadConfiguration(URL configFile) throws JoranException {
	    ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory();
	    int i = 0;
	    while(loggerFactory instanceof SubstituteLoggerFactory && i < 100) {
	      // slf4j is initialization phase
	      systemOut("SLF4J logger factory class: " + loggerFactory.getClass().getName()); //$NON-NLS-1$
	      try {
	        Thread.sleep(50);
	      } catch(InterruptedException e) {
	        e.printStackTrace();
	      }
	      i++ ;
	      loggerFactory = LoggerFactory.getILoggerFactory();
	    }
	    if(!(loggerFactory instanceof LoggerContext)) {
	      if(loggerFactory == null) {
	        // Is it possible?
	        systemErr("SLF4J logger factory is null"); //$NON-NLS-1$
	        return;
	      }
	      systemErr("SLF4J logger factory is not an instance of LoggerContext: " //$NON-NLS-1$
	          + loggerFactory.getClass().getName());
	      return;
	    }

	    getDefaultConsole().info("Initializing logback");
	    systemOut("Initializing logback"); //$NON-NLS-1$
	    LoggerContext lc = (LoggerContext) loggerFactory;
	    lc.reset();

	    JoranConfigurator configurator = new JoranConfigurator();
	    configurator.setContext(lc);
	    configurator.doConfigure(configFile);
	    
	    //lc.getl
	    
	    Logger logger=lc.getLogger("root");// (Logger) LoggerFactory.getLogger(GswwPluginActivator.class);
//	    EclipseLogAppender eclipseLogAppender = new EclipseLogAppender();
//	    eclipseLogAppender.start();
//	    logger.addAppender(eclipseLogAppender);
	    ToolSuiteConsoleAppender jdpAppender = new ToolSuiteConsoleAppender();
	    jdpAppender.start();
	    logger.addAppender(jdpAppender);
	    
	    //configurator.do

	    StatusPrinter.printInCaseOfErrorsOrWarnings(lc);

	    LogbackHelper.logJavaProperties(LoggerFactory.getLogger(LogActivator.class));
	  }

	
	public static void systemOut(String message) {
		System.out.println(PLUGIN_ID + ": " + message); //$NON-NLS-1$
		
	}

	public static void systemErr(String message) {
		System.err.println(PLUGIN_ID + ": " + message); //$NON-NLS-1$
	}
	
	/**
	 * Returns the shared instance
	 *
	 * @return the shared instance
	 */
	public static LogActivator getDefault() {
		return plugin;
	}

	/**
	 * Returns an image descriptor for the image file at the given
	 * plug-in relative path
	 *
	 * @param path the path
	 * @return the image descriptor
	 */
	public static ImageDescriptor getImageDescriptor(String path) {
		return imageDescriptorFromPlugin(PLUGIN_ID, path);
	}

}
